#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
批量修改Java项目包名脚本
功能：
1. 修改文件夹路径名
2. 修改module名
3. 修改代码和pom等文件中的包名引用
"""

import os
import re
import sys
import argparse
from pathlib import Path

class PackageRenamer:
    def __init__(self, project_root, old_package, new_package, old_module_prefix=None, new_module_prefix=None):
        self.project_root = Path(project_root).absolute()
        self.old_package = old_package
        self.new_package = new_package
        self.old_package_path = old_package.replace('.', os.sep)
        self.new_package_path = new_package.replace('.', os.sep)
        self.old_module_prefix = old_module_prefix
        self.new_module_prefix = new_module_prefix
        
        # 支持的文件类型
        self.supported_files = [
            '*.java', '*.pom', '*.xml', '*.properties', 
            '*.gradle', '*.groovy', '*.kt', '*.kts'
        ]
        
        print(f"项目根目录: {self.project_root}")
        print(f"旧包名: {self.old_package} -> 新包名: {self.new_package}")
        print(f"旧路径: {self.old_package_path} -> 新路径: {self.new_package_path}")
        
        if self.old_module_prefix and self.new_module_prefix:
            print(f"旧Module前缀: {self.old_module_prefix} -> 新Module前缀: {self.new_module_prefix}")
    
    def find_package_folders(self):
        """查找所有包含旧包名的文件夹"""
        package_folders = []
        
        for root, dirs, files in os.walk(self.project_root):
            # 检查当前路径是否包含旧包名路径
            if self.old_package_path in root.replace(str(self.project_root), ''):
                package_folders.append(Path(root))
        
        # 按路径深度排序，从深到浅，确保先修改子文件夹
        package_folders.sort(key=lambda x: len(x.parts), reverse=True)
        return package_folders
    
    def rename_folders(self):
        """重命名包含旧包名的文件夹"""
        package_folders = self.find_package_folders()
        
        if not package_folders:
            print(f"未找到包含旧包名 '{self.old_package}' 的文件夹")
            return
        
        print(f"\n找到 {len(package_folders)} 个需要重命名的文件夹：")
        for folder in package_folders:
            print(f"  - {folder}")
        
        # 重命名文件夹
        for folder in package_folders:
            # 构建新路径
            relative_path = folder.relative_to(self.project_root)
            new_relative_path = str(relative_path).replace(self.old_package_path, self.new_package_path)
            new_folder = self.project_root / new_relative_path
            
            # 创建父目录（如果不存在）
            new_folder.parent.mkdir(parents=True, exist_ok=True)
            
            # 重命名文件夹
            print(f"\n重命名文件夹：")
            print(f"  旧路径: {folder}")
            print(f"  新路径: {new_folder}")
            
            try:
                folder.rename(new_folder)
                print(f"  ✅ 重命名成功")
            except Exception as e:
                print(f"  ❌ 重命名失败: {e}")
    
    def rename_modules(self):
        """重命名包含旧module前缀的文件夹"""
        if not self.old_module_prefix or not self.new_module_prefix:
            return
        
        # 查找所有直接子目录，检查是否以旧module前缀开头
        module_folders = []
        for item in self.project_root.iterdir():
            if item.is_dir() and item.name.startswith(self.old_module_prefix):
                module_folders.append(item)
        
        if not module_folders:
            print(f"\n未找到以旧Module前缀 '{self.old_module_prefix}' 开头的文件夹")
            return
        
        print(f"\n找到 {len(module_folders)} 个需要重命名的Module文件夹：")
        for folder in module_folders:
            print(f"  - {folder.name}")
        
        # 重命名Module文件夹
        for folder in module_folders:
            new_name = folder.name.replace(self.old_module_prefix, self.new_module_prefix)
            new_folder = folder.parent / new_name
            
            print(f"\n重命名Module文件夹：")
            print(f"  旧名称: {folder.name}")
            print(f"  新名称: {new_name}")
            
            try:
                folder.rename(new_folder)
                print(f"  ✅ 重命名成功")
            except Exception as e:
                print(f"  ❌ 重命名失败: {e}")
    
    def find_files_to_modify(self):
        """查找所有需要修改内容的文件"""
        files_to_modify = []
        
        for file_pattern in self.supported_files:
            for file_path in self.project_root.rglob(file_pattern):
                files_to_modify.append(file_path)
        
        return files_to_modify
    
    def replace_in_file(self, file_path):
        """替换文件中的旧包名和旧module名为新包名和新module名"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 统计替换前的匹配次数
            old_count = content.count(self.old_package)
            
            # 如果有module前缀，也统计module的匹配次数
            if self.old_module_prefix and self.new_module_prefix:
                old_count += content.count(self.old_module_prefix)
            
            if old_count == 0:
                return 0
            
            # 替换包名
            new_content = content.replace(self.old_package, self.new_package)
            
            # 如果有module前缀，也替换module名
            if self.old_module_prefix and self.new_module_prefix:
                new_content = new_content.replace(self.old_module_prefix, self.new_module_prefix)
            
            # 写回文件
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(new_content)
            
            return old_count
        except Exception as e:
            print(f"  ❌ 处理文件失败 {file_path}: {e}")
            return 0
    
    def modify_file_contents(self):
        """修改所有文件中的包名引用"""
        files_to_modify = self.find_files_to_modify()
        total_replaced = 0
        modified_files = 0
        
        print(f"\n开始处理文件内容，共找到 {len(files_to_modify)} 个文件")
        
        for file_path in files_to_modify:
            replaced = self.replace_in_file(file_path)
            if replaced > 0:
                modified_files += 1
                total_replaced += replaced
                print(f"  ✅ {file_path}: 替换了 {replaced} 处")
        
        print(f"\n文件内容修改完成：")
        print(f"  处理文件数: {len(files_to_modify)}")
        print(f"  修改文件数: {modified_files}")
        print(f"  替换总次数: {total_replaced}")
    
    def run(self):
        """执行完整的包名和module名修改流程"""
        print("\n" + "="*60)
        print("开始执行Java项目包名和module名修改")
        print("="*60)
        
        # 1. 重命名module文件夹
        self.rename_modules()
        
        # 2. 重命名包名文件夹
        self.rename_folders()
        
        # 3. 修改文件内容
        self.modify_file_contents()
        
        print("\n" + "="*60)
        print("包名和module名修改完成！")
        print("="*60)

def main():
    parser = argparse.ArgumentParser(description="批量修改Java项目包名和module名脚本")
    parser.add_argument("project_root", help="Java项目根目录")
    parser.add_argument("old_package", help="旧包名，例如：com.example.old")
    parser.add_argument("new_package", help="新包名，例如：com.example.new")
    parser.add_argument("--old-module", help="旧module前缀，例如：yudao-")
    parser.add_argument("--new-module", help="新module前缀，例如：ccxiezuo-")
    
    args = parser.parse_args()
    
    renamer = PackageRenamer(
        args.project_root, 
        args.old_package, 
        args.new_package,
        args.old_module,
        args.new_module
    )
    renamer.run()

if __name__ == "__main__":
    main()
